import json
import logging
import os
import pathlib
import shutil
import subprocess
from fileinput import FileInput

logger = logging.getLogger('abaqus')


def run_native_simulation(sim_config):
    entry = sim_config['model']['entry']
    # 支持inp文件
    run_inp(sim_config)


def run_inp(sim_config):
    # 替换参数
    parameters = sim_config.get('parameters', [])
    model_file = pathlib.Path(
        sim_config['model']['file'], sim_config['model']['entry'])
    inp_file = sim_config['model']['entry']
    with FileInput(model_file, inplace=True, backup='.bak') as f:
        for line in f:
            p_start_index = line.find("{{")
            p_end_index = line.find("}}")
            if p_start_index >= 0 and p_end_index >= 0:
                p_sep_index = line.find(":", p_start_index, p_end_index)
                if p_sep_index >= 0:
                    replaced_flag = False
                    for p in parameters:
                        if line.find(p['org']) >= 0:
                            line = line.replace(p['org'], p['value'])
                            replaced_flag = True
                    if not replaced_flag:
                        line = line[:p_start_index] + line[p_sep_index +
                                                           1:p_end_index] + line[p_end_index+2:]
            print(line, end='')
    # 运行仿真
    cmd = f'abaqus Job={inp_file}'
    sp = subprocess.Popen(f'{cmd}', cwd=sim_config['model']['file'], shell=True, stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE,
                          encoding='UTF-8')
    out_info, err_info = sp.communicate()
    logger.info(f'run out info: {out_info}')
    logger.info(f'run err info: {err_info}')
    # 处理odb仿真结果
    odbFileName = sim_config['model']['entry'].split(".")[0] + ".odb"
    odbFilePath = pathlib.Path(sim_config['model']['file'], odbFileName)
    logger.info(f'odbFilePath = {odbFilePath}')
    # 将odb文件返回，不支持输出参数的结果提取
    if sim_config['result']['uploadRawSimResult']:
        result_dir = pathlib.Path(sim_config['model']['file'], 'results')
        os.mkdir(result_dir)
        shutil.copy(odbFilePath, result_dir)
        simulationResultDir = str(result_dir)
    # 定制解析odb的脚本
    with open("script/parseOdb.py", "r") as file:
        data = file.read()
    output_path = os.path.join(sim_config['model']['file'], "result.json")
    data = data.format_map(
        {"odb_path": odbFilePath, "output_path": output_path})
    parse_odb_script = os.path.join(simulationResultDir, "parse_odb.py")
    with open(parse_odb_script, "w") as file:
        file.write(data)
    cmd = f'abaqus cae noGui={parse_odb_script}'
    sp = subprocess.Popen(f'{cmd}', cwd=sim_config['model']['file'], shell=True, stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE,
                          encoding='UTF-8')
    out_info, err_info = sp.communicate()
    logger.info(f'run out info: {out_info}')
    logger.info(f'run err info: {err_info}')
    output_file = sim_config['outputFilePath']
    output = {
        "simulationResultDir": simulationResultDir,
        "specifiedParameters": []
    }
    # 增加定制的场数据输出
    with open(output_path, "r") as file:
        data = json.load(file)
    output["specifiedParameters"].append({
        "name": "node_displacement",
        "mdoLabel": "node_displacement",
        "type": "json",
        "value": data["nodes"]
    })
    output["specifiedParameters"].append({
        "name": "element_stress",
        "mdoLabel": "element_stress",
        "type": "json",
        "value": data["elements"]
    })
    simulationOutput = {
        "success": True,
        "message": "",
        "data": output
    }
    # 驱动运行结果写入output.json文件
    with open(output_file, 'w') as f:
        json.dump(simulationOutput, f)
